<?php

/**
 * Albireo Kernel
 *
 * @copyright  Copyright (c) 2010 Albireo Solutions
 * @package    Kernel
 */

namespace KernelModule\UsersModule;

use Albireo\Forms\AlbireoForm;
use Nette\Application\AppForm;
use Nette\Forms\Form;
use \dibi;

use KernelModule\AclModule\AclRole;
use KernelModule\AclModule\AclManagement;
use Celebrio\AccessControl\UserManagement;

/**
 * Roles
 *
 * @inherits cancelClicked() from Kernel\Acl\BasePresenter
 * @inherits addFormButtons from Kernel\Acl\BasePresenter
 * @inherits createComponentDelete() from Kernel\Acl\BasePresenter
 *
 * @author Pavel
 */
class RolesPresenter extends \KernelModule\AclModule\BasePresenter {

    /** @var Kernel\UserManagment */
    private $rolesModel;

    /** @var KernelModule\AclModule\AclManagment */
    private $aclManager;

    /** @var Kernel\UserManagment */
    private $userManager;

    /**
     * Lazy getter for AclManagement
     * @return AclManagement
     */
    private function getAclManager() {
        if ($this->aclManager === NULL) {
            $this->aclManager = new AclManagement();
        }
        return $this->aclManager;
    }

    /**
     * Lazy getter for UserManagement
     * @return Celebrio\AccessControl\UserManagement
     */
    private function getUserManager() {
        if ($this->userManager === NULL) {
            $this->userManager = new UserManagement();
        }
        return $this->userManager;
    }

    /**
     * Lazy getter for RolesModel
     * @return use RolesModel
     */
    private function getRolesModel() {
        if ($this->rolesModel === NULL) {
            $this->rolesModel = new RolesModel();
        }
        return $this->rolesModel;
    }

    public function renderDefault() {
        $nodes = $this->getRolesModel();
        $this->template->title = _("Roles List");
        $this->template->nodes = $nodes;
        $this->template->parents = $nodes->getChildNodes(NULL);
    }

    
    public function actionAdd($id = 0) { // id = parent id
        $this->template->title = _("Add New Role");
        $form = $this->getComponent('addEdit');
        $form->setDefaults(array('parent_id' => $id));
    }

    //TODO presunout do modelu praci s databazi
    public function actionEdit($id) {
        $this->template->title = _("Edit Role");

        $sql = dibi::query('SELECT id, name, parent_id FROM ['.TABLE_ROLES.'] WHERE id=%i;', $id);
        $form = $this->getComponent('addEdit');
        if (count($sql)) {
            $row = $sql->fetch();
            if (empty($row->parent_id))
                $row->parent_id = 0;
            $form->setDefaults($row);
        }
        else
            $form->addError(_('This role does not exist.'));
        unset($sql);
    }

    protected function createComponentAddEdit() {
        $roles[0] = ' ';
        $mroles = $this->getRolesModel();
        $rows = $mroles->getTreeValues();
        foreach ($rows as $key => $row) { // function array_merge does't work correctly with integer indexes
            // manual array merge
            $roles[$key] = $row;
        }

        $form = new AlbireoForm();
        $form->addText('name', _('Name:'), 30)
            ->addRule(Form::FILLED, _('You have to fill name.'));
            //->getControlPrototype()->onChange("create_key()");
        $form->addSelect('parent_id', _('Parent:'), $roles, 15);
        
        $this->addFormButtons($form);
        
        return $form;
    }

    public function addOrEditSubmitted(AlbireoForm $form) {

        $values = $form->getValues();

        $newRole = new AclRole();
        $newRole->setName($values["name"]);
        $newRole->setParentId($values["parent_id"] == 0 ? null : $values["parent_id"]);
        
        if ($this->getAction() == "add") {
            if ($this->getAclManager()->addRole($newRole)) {
                $this->flashMessage(_('The role has been added.'), 'ok');
            } else {
                $this->flashMessage(_("The role can't be added, maybe already exists."), 'error');
            }
        } elseif($this->getAction() == "edit") {

            $rolesModel = $this->getRolesModel();
            $childNodes = array();
            $rolesModel->getParents($values["id"], $childNodes, 0);

            // is the new parent_id in the sub-tree of the current role?
            if (isset($childNodes[$values["parent_id"]]) || $values["parent_id"] == $values["id"]) {
                $this->flashMessage(_('The new parent role is invalid.'), 'error');
                $this->redirect("default");
            }

            $newRole->setId($values["id"]);
            if ($this->getUserManager()->updateRole($newRole)) {
                $this->flashMessage(_('The role has been edited.'), 'ok');
            } else {
                $this->flashMessage(_("The role can't be updated."), 'error');
            }
        } else throw new \InvalidStateException(); //this should never happen
        $this->redirect("default");
    }


    public function actionDelete($id) {
        $deletedRole = $this->getUserManager()->getRoleById($id);
        if ($deletedRole == NULL) {
            $this->flashMessage(_("The role doesn't exist."), "error");
            $this->redirect('default');
        }
        $this->template->title = _("Delete Role");
        $this->template->name = $deletedRole->getName();
        $this["delete"]->setDefaults(array("id" => $deletedRole->getId()));
    }

    public function deleteOnFormSubmitted(AppForm $form){
        if ($form['delete']->isSubmittedBy()) {
            $values = $form->getValues();
            $deletedRole = $this->getUserManager()->getRoleById($values["id"]);
            if ($this->getAclManager()->deleteFromAcl($deletedRole)) {
                $this->flashMessage(_('The role has been deleted succesfuly.'), 'ok');
            } else $this->flashMessage(_("The role has not been deleted. Other roles depend on it."), "error");
        }
        $this->redirect("default");
    }

    
    public function actionUsers($id) {
        $this->template->title = _("Users For The Role");
        $this->template->users = $this->getUserManager()->getUsersForRole($id);
        $this->template->role = $this->getUserManager()->getRoleById($id);
    }

    
    public function actionAccess($id) {
        $this->template->title = _("Access For The Role");
        
        $access = $this->getAclManager()->getAccessForTheRole($id);
        $lastResourceName = "";
        for($ii=0; $ii<count($access); $ii++) {
            if ($access[$ii]["resource"] == $lastResourceName) {
                $access[$ii]["resource"] = "--||--";
            } else {
                $lastResourceName = $access[$ii]["resource"];
            }
        }

        $this->template->access = $access;
        $this->template->role = $this->getUserManager()->getRoleById($id)->getName();
    }
}